﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Kyoh.Lib.Enumerates4
{
    public static class Enumerate
    {
        public static TSource TryFirst<TSource, TException>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
            where TException : Exception
        {
            return Enumerate.TryFirst<TSource, TException>(source, predicate, (i, x) => false);
        }
        public static TSource TryFirst<TSource, TException>(this IEnumerable<TSource> source, Func<TSource, bool> predicate, bool onError)
            where TException : Exception
        {
            return Enumerate.TryFirst<TSource, TException>(source, predicate, (i, x) => onError);
        }
        public static TSource TryFirst<TSource, TException>(this IEnumerable<TSource> source, Func<TSource, bool> predicate, Func<TSource, TException, bool> onError)
            where TException : Exception
        {
            return Enumerable.First(source, item =>
            {
                try { return predicate(item); }
                catch (TException exc) { return onError(item, exc); }
            });
        }
        public static TSource TryFirstOrDefault<TSource, TException>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
            where TException : Exception
        {
            return Enumerate.TryFirstOrDefault<TSource, TException>(source, predicate, (i, x) => false);
        }
        public static TSource TryFirstOrDefault<TSource, TException>(this IEnumerable<TSource> source, Func<TSource, bool> predicate, bool onError)
            where TException : Exception
        {
            return Enumerate.TryFirstOrDefault<TSource, TException>(source, predicate, (i, x) => onError);
        }
        public static TSource TryFirstOrDefault<TSource, TException>(this IEnumerable<TSource> source, Func<TSource, bool> predicate, Func<TSource, TException, bool> onError)
            where TException : Exception
        {
            return Enumerable.FirstOrDefault(source, item =>
            {
                try { return predicate(item); }
                catch (TException exc) { return onError(item, exc); }
            });
        }
    }
}
